﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.AccessControl;

namespace HomeWork7
{
    internal class Program
    {
        //1.定义一个使用文件流复制文件的方法
        private static void Main1(string[] args)
        {
            string path = @"E:\Learn Unity\File.txt";
            string aimPath = @"E:\Learn Unity\CopyToFile.txt";
            CopyFileStream(path, aimPath);
        }

        private static void CopyFileStream(string path, string aimpath)//将一个文件中的内容通过文件流复制到另外一个文件中
        {
            FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read);//创建一个只读的文件流
            byte[] bytes = new byte[2048];//创建一个缓存区
            FileStream fsWrite = new FileStream(aimpath, FileMode.Create, FileAccess.Write);//创建一个只写的文件流
            while (true)
            {
                //length每次真实读取到的数据
                int length = fsRead.Read(bytes, 0, bytes.Length);//从流中读取字节并将该数据写入给定缓冲区中
                if (length == 0)//如果真实读取到的数据为0,则表示已经读取完毕,那么就退出循环
                {
                    break;
                }
                fsWrite.Write(bytes, 0, length);//将fsRead真实读取到的数据写入缓冲区中
                Console.WriteLine($"文件共{fsRead.Length}字节,本次读取{length}字节,当前位置{fsRead.Position}");
                Console.ReadLine();
            }
            fsWrite.Flush();//把底层缓冲区的数据全部写入文件
            Console.WriteLine("复制完成");
            fsRead.Close();//关闭文件流  节约资源
            fsWrite.Close();
        }

        //2..自学递归(方法自己调自己),能在控制台输出D盘所有文件的文件路径
        private static void Main2(string[] args)
        {
            //string[] str = Directory.GetDirectories(@"D:\");
            string path = @"D:\";
            GetFilesPath(path);
        }

        private static void GetFilesPath(string path)
        {
            string[] dire = Directory.GetDirectories(path);//获取当前目录下所有子目录
            string[] files = Directory.GetFiles(path);//获取当前文件夹下面所有文件
            foreach (var item in files)//输出当前获取到的文件
            {
                Console.WriteLine(item);
            }
            for (int i = 0; i < dire.Length; i++)
            {
                try
                {
                    GetFilesPath(dire[i]);//继续调用此方法
                }
                catch (Exception)
                {
                    Console.WriteLine("权限不够，无法访问！");//抛出无法访问的文件
                }
            }
        }

        //3..Ini文件读取类IniFile
        //可以使用如下的方式访问拿到ip地址:
        //需要你来写IniFile这个类
        //IniFile ini=new IniFile();
        //ini.ReadFile(@"D:\config.txt");
        //string ip = ini.GetString("连接信息", "主机")
        //print(ip);//输出192.168.2.254
        private static void Main(string[] args)
        {
            IniFile file = new IniFile();//创建一个file对象
            string path = @"E:\Learn Unity\Config.txt";
            file.ReadFile(path);
            string s = file.GetString("[设置]", "音量");
            Console.WriteLine(s);
        }
    }

    internal class IniFile
    {
        private Dictionary<string, Dictionary<string, string>> ini = new Dictionary<string, Dictionary<string, string>>();//为了保证键的唯一性 这里需要定义两个字典

        //设置键值对方法
        public void ReadFile(string path)
        {
            //string str = File.ReadAllText(path);//获取到的所有文本内容
            //string[] lines = str.Split('\n');//通过换行符获取到每一行的信息
            //那么为什么不直接以行读取文本呢
            string[] lines = File.ReadAllLines(path);//以行获取到所有文本内容
            string mainKey = "";//定义一个空值主键
            string sconendKey = "";//定义一个次要的键
            string value = "";//定义一个空值
            for (int i = 0; i < lines.Length; i++)
            {
                if (lines[i] == "") continue;//跳过空行
                if (lines[i].StartsWith("[") == true)//如果字符串以"["开头 就把这一行的值设置为主键
                {
                    // mainKey = lines[i].Substring(0, lines.Length - 2);//去除"[]"
                    mainKey = lines[i];
                    ini.Add(mainKey, new Dictionary<string, string>());
                }
                else if (lines.Contains("="))//判断是否有等号
                {
                    string[] kv = lines[i].Split('=');//用等号划分后面的键值对 基数为值  偶数为键
                    for (int j = 0; j < kv.Length; j++)
                    {
                        if (kv.Length % 2 == 0)//如果是偶数
                        {
                            sconendKey = kv[j];
                        }
                        else
                        {
                            value = kv[j];
                        }
                        ini[mainKey].Add(sconendKey, value);//将所有键值对表示出来
                    }
                }
            }
        }

        //设置给主键和次键获取值的信息
        public string GetString(string mainKey, string secondKey)
        {
            return ini[mainKey][secondKey];
        }
    }
}